package com.qingdai.securityauth.filter;

import com.alibaba.fastjson2.JSON;
import com.qingdai.business.emuns.User;
import com.qingdai.business.entities.CommonResult;
import com.qingdai.business.service.UserService;
import com.qingdai.business.utils.AuthoritiesUtil;
import com.qingdai.business.utils.JwtUtil;
import com.qingdai.business.utils.WebUtil;
import com.qingdai.securityauth.config.RequestConfig;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcServiceContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class JwtCheckBeforeAuthorizationFilter extends OncePerRequestFilter {
    @Resource
    private JwtUtil jwtUtil;
    @DubboReference
    private UserService userService;
    @Resource
    private RequestConfig requestConfig;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private AuthoritiesUtil authoritiesUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        RpcServiceContext ctx = RpcContext.getServiceContext();
        if (ctx.getVersion() == null) {
//            return invoker.invoke(invocation);
        }
        //        如果是登录请求直接放行
        if (requestConfig.check(request)) {
            doFilter(request, response, filterChain);
        } else {
            CommonResult result = jwtUtil.getUserIdByRequest(request);
            if (result.getCode() == 200) {
                Integer userId = (Integer) result.getData();
                String RedisToken = (String) redisTemplate.opsForValue().get("loginToken-UserId:" + userId);
                if (RedisToken == null) {
                    String result1 = JSON.toJSONString(new CommonResult<>(400, "请重新登录"));
                    WebUtil.renderString(response, result1);
                } else {
                    User userByUserId = userService.getUserByUserId(userId);
                    List<String> authorities = authoritiesUtil.getAuthoritiesByUserId(userId);
                    List<SimpleGrantedAuthority> authorityList = authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
                    org.springframework.security.core.userdetails.User userDetail =
                            new org.springframework.security.core.userdetails.User(
                                    userByUserId.getUsername(), //用户名
                                    userByUserId.getPassword(), //登录用户的密码，是服务端保存到密文
                                    AuthorityUtils.createAuthorityList(String.valueOf(authorities))//通过工具，把字符串权限转换成Security定义的权限
                            );

                    //用户名密码认证token
                    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetail,
                            null, authorityList);
                    //把token放到上下文
                    SecurityContextHolder.getContext().setAuthentication(token);

                    //放行
                    doFilter(request, response, filterChain);
                }
            } else {
                String result1 = JSON.toJSONString(result);
                WebUtil.renderString(response, result1);
            }
        }
    }
}


